上篇component元件有說到每個元件範圍都應該是獨立的,更不應該發生子元件直接改變根元件的情況,元件與元件又該怎麼正確傳遞資料呢?
Props起手式子元件做好之後,為了能重複使用,就會使用外部元件的資料,供傳子元件使用,但是又不能靠子元件直接取用,這時就用使用props屬性來完成。
<div id="app">
<h4>{{ text }}</h4>
<con-tainer :test-props="demo"></con-tainer>
</div>
:test-props="demo",前面的:test-props是內層元件,後面的"demo"是外層元件,好記的方式:前內後外。
const app = Vue.createApp({
data() {
return {
text: "外部元件",
demo: "外部元件傳遞的文字"
};
}
});
app.component("ConTainer", {
props: ["testProps"],
template: `<div>
<h4>{{ text }}</h4><h3>{{ testProps }}<h3>
</div>`
});
app.mount("#app");
內部元件的props屬性宣告從外部引入到內部元件,並且透過外層模板的v-bind完成兩個元件的資料傳遞,HTML可以說是兩個元件溝通的橋樑。
補充:``props命名有使用駝峰命名,記得寫在模板時要改為連字號,因為HTML不分大小寫,例如:props: ["testProps"]的testProps要改為test-props。
props單向數據流當內層元件想使用v-model來改變外層元件的資料時會跳出這行警告,[Vue warn]: Attempting to mutate prop "test". Props are readonly.,Props是有讀取限制的。
<div id="app">
<con-tainer :test-props="demo"></con-tainer>
</div>
const app = Vue.createApp({
data() {
return {
demo: "外部元件傳遞的文字"
};
}
});
app.component("ConTainer", {
props: ["testProps"],
template: `<div>
<h3>{{ testProps }}<h3>
<input type="text" v-model="testProps">
</div>`
});
app.mount("#app");
props時有v-bind與沒有v-bind的區別觀察import-num有無綁定v-bind的差別:
<div id="app">
<con-tainer import-num="400"></con-tainer>
<con-tainer :import-num="num"></con-tainer>
</div>
const app = Vue.createApp({
data() {
return {
num: 500
};
}
});
app.component("ConTainer", {
props: ["importNum"],
template: `<div>
<h3>value: {{ importNum }} </h3>
<h3>value: {{ typeof importNum }} </h3>
</div>`
});
app.mount("#app");
在外部元件的模板裡,未綁定v-bind的情況下,內部元件props依然可以接受資料,任何值傳入到內部元件props都會是string的型別。有綁定v-bind就會依據外部元件data的num型別,內部也會顯示該型別。
props型別驗證多人開發有時會需要驗證外部元件props傳入的型別,這時就可以使用型別驗證的技巧,來得知適當的提示。
上面範例在內元件中props都是使用陣列方式(可以帶多個值),例如props:['one','two'],如果要進行驗證,就要改為大括號物件的形式。
準備好一個內部元件areaComponent,console.log還不會跳出提示:
<div id="app">
<area-component
:pro-a="fun" :pro-b="text"
pro-c="num" :pro-d="num">
</area-component>
</div>
const areaComponent = {
props: {
proA: Function,
//多個型別檢查
proB: [String, Number],
//必要值 物件形式可以設立多個條件
proC: {
type: String,
required: true
},
//預設值
proD: {
type: Number,
default: "hello"
}
},
template: `{{ proA }} <br> {{ proB }} <br> {{ proC }} <br> {{ proD }}`
};
const app = Vue.createApp({
data() {
return {
num: 500,
text: "小明",
boo: true,
fun: () => {
return "a";
},
test: 100
};
},
components: {
areaComponent
}
});
app.mount("#app");
將上面範例程式碼內部元件:pro-a="fun"的fun改為text:
<div id="app">
<area-component :pro-a="text" :pro-b="text" pro-c="num" :pro-d="num"></area-component>
</div>
此時console.log就會跳出提示:[Vue warn]: Invalid prop: type check failed for prop 'proA'. Expected Function, got String with value '小明'.
意思是預期應該是一個Function,但傳入結果卻是字串。
required: true:一定要給一個值,如果沒有就會跳出提示。default: "hello":當沒有透過props傳入值,畫面就會給出hello的預設值,可以將:pro-d="num"移除看出差異在哪裡。pro-c="num":console.log為什麼沒跳出提示?因為沒綁定v-bind,都會自動變成String型別。
以上如有錯誤,歡迎指教
![]()